<template>
  <div class="mainView">
    <div class="processbar">
      <div class="processline" id="processline"></div>
    </div>
    <div class="toolbar">
      <div class="title">长:</div><input type="number" v-model="width" />
      <div class="title">高:</div><input type="number" v-model="height" />
      <div class="title">任务数:</div><input type="number" v-model="taskCount" />
      <input type="checkbox" v-model="slowImage" id="slowImage" name="slowImage" />
      <label for="slowImage">慢速渲染</label>
    </div>
    <div class="buttonGroup">
      <button @click="handleRender('simple')">简单渲染</button>
      <button @click="handleRender('scene')">场景渲染</button>
      <button @click="handleRender('camera')">相机渲染</button>
      <button @click="handleRender('sphereOne')">单球体渲染</button>
      <button @click="handleRender('sphereMore')">多球体渲染</button>
      <button @click="handleRender('reflect')">反射渲染</button>
      <button @click="handleRender('reflectAttenuation')">反射衰减</button>
      <button @click="handleRender('material')">材质渲染</button>
      <button @click="handleRender('materialFuzz')">材质粗糙</button>

    </div>
    <canvas id="cv" :style="{ width: `${width}px`, height: `${height}px` }"></canvas>
  </div>
</template>
<script setup lang="ts">
import { ref, onMounted, computed, watch } from 'vue'
import { RenderTask } from './commonTypes'
import TaskWorker from './taskWorker?worker'
import { initTasks3 } from './taskUtil'

// 图片尺寸
const height = ref(400)
const width = ref(800)
// 任务总数
const taskCount = ref(4)
// 像素总数量
const pxielAmount = computed(() => {
  return height.value * width.value
})
// 慢速渲染
const slowImage = ref(false)
// 渲染类型
const renderType = ref('simple')

// 渲染资源
let ctx: CanvasRenderingContext2D | null = null
let image: ImageData | undefined = undefined
let progressBar: HTMLElement | null = null
let complete = 0
let tasks: RenderTask[] = []
let needInit: boolean = false

watch([height, width, taskCount], () => {
  needInit = true
})

onMounted(() => {
  needInit = true
  // // 执行任务
  // performTasks()
})

function performTasks() {
  init()

  // 重置进度
  complete = 0

  // 清空图片缓存
  image = ctx?.createImageData(width.value, height.value)

  // 执行任务
  for (let task of tasks) {
    performTask(task)
  }
}

function init() {
  if (!needInit) {
    return
  }
  needInit = false
  // 设定图片尺寸
  const canvas = document.getElementById('cv') as HTMLCanvasElement
  canvas.height = height.value
  canvas.width = width.value

  // 获得图片渲染上下文 
  ctx = canvas.getContext('2d')

  // 获得进度条
  progressBar = document.getElementById('processline')

  // 初始化任务
  tasks = initTasks3(width.value, height.value, taskCount.value)
}

/**
 * 通过webworker建立像素点，并进行渲染
 * @param task 
 */
function performTask(task: RenderTask) {
  const worker = new TaskWorker()

  worker.onmessage = (e: any) => {
    const { data } = e
    if (data.type === 'init') {
      // 当worker初始化完毕，发送渲染命令和参数
      worker.postMessage({
        type: 'render',
        task: task,
        renderType: renderType.value
      })
    } else if (data.type === 'partComplete') {
      const tmpTask = data.task
      if (tmpTask) {
        renderImageFromTask(tmpTask, slowImage.value)
      }
    } else if (data.type === 'allComplete') {
      // 关闭worker
      worker.terminate()
      // 渲染最后一张图
      const tmpTask = data.task
      if (tmpTask) {
        renderImageFromTask(tmpTask)
      }
    }
  }
}

/**
 * 渲染任务信息到图片并更新进度
 * @param task 
 */
function renderImageFromTask(task: RenderTask, renderImage = true) {
  if (image) {
    // 设置像素点颜色
    for (let px of task.pixels) {
      let pos = (px.x + px.y * task.width) * 4
      image.data[pos++] = px.r
      image.data[pos++] = px.g
      image.data[pos++] = px.b
      image.data[pos++] = px.a
    }

    // 绘制图片
    if (renderImage) {
      ctx?.putImageData(image, 0, 0)
    }
  }

  // 更新进度的百分比
  complete += task.pixels.length
  if (progressBar) {
    const percent = Math.min(100, (complete / pxielAmount.value) * 100)
    progressBar.style.width = `${percent}%`
  }
}

function handleRender(_renderType: string) {
  renderType.value = _renderType
  performTasks()
}


</script>
<style scoped>
.mainView {
  width: 100%;
  height: 100%;
  position: relative;
  background-color: yellowgreen;


  & canvas {
    position: absolute;
    left: 50%;
    top: 120px;
    transform: translate(-50%, 0);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.8)
  }
}

.processbar {
  width: 100%;
  height: 4px;
  position: absolute;
  top: 0;
  background: #fff;
}

.processline {
  width: 100%;
  height: 100%;
  background-color: #0e2f8c
}

.toolbar {
  position: absolute;
  top: 20px;
  left: 0px;
  right: 0px;
  display: flex;
  gap: 5px;
  justify-content: center;

  .title {
    flex-basis: content;
  }

  z-index: 100;
}

.buttonGroup {
  position: absolute;
  top: 60px;
  left: 0px;
  right: 0px;
  z-index: 100;

  display: flex;
  gap: 5px;
  flex-wrap: wrap;
  justify-content: center;

}
</style>